﻿using Abp.BackgroundJobs;
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using Abp.Domain.Uow;
using Mt.Site.Core.BackGroundJobs;
using Mt.Site.Core.BackGroundJobs.Storage;
using Mt.Site.Core.Navigations.Entities;
using Mt.Site.Core.Storage;
using Mt.Site.Core.Synchronization.Data;
using System;

namespace Mt.Site.Core.Synchronization.Storage
{
    public class FileObjectManualSyncManager:DomainService,IFileObjectManualSyncManager
    {

        private readonly IRepository<FileObject, Guid> _fileObjectRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        private readonly IFileObjectDataStoreManager _fileObjectDataStoreManage;

        private readonly ISynchronizationHelper _synchronizationHelper;

        private readonly IBackgroundJobManager _backgroundJobManager;

        private readonly IRepository<Menu, Guid> _menuRepository;

        public FileObjectManualSyncManager(
            IRepository<FileObject, Guid> fileObjectRepository,
            IUnitOfWorkManager unitOfWorkManager,
            IFileObjectDataStoreManager fileObjectDataStoreManage,
            ISynchronizationHelper synchronizationHelper,
            IBackgroundJobManager backgroundJobManager,
            IRepository<Menu, Guid> menuRepository)
        {
            _fileObjectRepository = fileObjectRepository;
            _unitOfWorkManager = unitOfWorkManager;
            _fileObjectDataStoreManage = fileObjectDataStoreManage;
            _synchronizationHelper = synchronizationHelper;
            _backgroundJobManager = backgroundJobManager;
            _menuRepository = menuRepository;
        }

        [UnitOfWork]
        public Guid CreateOrUpdateFileObjectByMenuManualSync(CreateOrUpdateSynchorizeStore input)
        {
            if (!_synchronizationHelper.ShouldSynchronize(input.ToTenantId))
            {
                return Guid.Empty;
            }
            using (_unitOfWorkManager.Current.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage,
                AbpDataFilters.SoftDelete))
            {
                var fromEntity = _fileObjectRepository.FirstOrDefault(item=>item.Id == input.Id && item.IsDeleted == false);
                
                if (fromEntity == null)
                {
                    return Guid.Empty;
                }

                var toEntity = _fileObjectRepository.FirstOrDefault(
                        item => item.SourceID == fromEntity.Id && item.Language == input.TargetLanguage && item.TenantId == input.ToTenantId);
                var toId = Guid.Empty;

                if (toEntity == null)
                {
                    var toContentId = GetTargetMenuId(fromEntity.ContentId, input.ToTenantId);
                    if (toContentId != Guid.Empty)
                    {
                        toId = _fileObjectDataStoreManage.CreateFileObjectSync(fromEntity, new DataProcessingStore
                        {
                            TargetLanguage = input.TargetLanguage,
                            ToTenantId = input.ToTenantId,
                            AssociateId = toContentId
                        });
                        input.OptionType = OptionType.Create;
                    }
                    
                }
                else
                {
                    toId = _fileObjectDataStoreManage.UpdateFileObjectSync(toEntity, fromEntity);
                    input.OptionType = OptionType.Update;
                }

                if (toId != Guid.Empty)
                {
                    _backgroundJobManager.Enqueue<SynchorizationFileObjectJob, BaseAndMenuIdArgs>(
                            new BaseAndMenuIdArgs
                            {
                                FromLanguage = input.TargetLanguage,
                                FromTenantId = input.ToTenantId,
                                Id = fromEntity.Id,
                                OperateType = input.OptionType
                            });
                }
                return toId;
            }
        }


        public Guid GetTargetMenuId(Guid menuId, int toTenantId)
        {
            var fromMenu = _menuRepository.FirstOrDefault(menuId);
            if (fromMenu != null)
            {
                var toMenu = _menuRepository.FirstOrDefault(item => item.AuxiliaryId == fromMenu.AuxiliaryId && item.TenantId == toTenantId);

                if (toMenu != null)
                {
                    return toMenu.Id;
                }
            }
            return Guid.Empty;
        }

        /// <summary>
        /// 仅给其他方法调用
        /// </summary>
        /// <param name="input"></param>
        /// <param name="toContentId"></param>
        /// <returns></returns>
        [UnitOfWork]
        public void CreateOrUpdateFileObjectManualSync(FileObjectSyncStore input)
        {
            var fromFileObjects = _fileObjectRepository.GetAllList(
                    item => item.ContentId == input.FromContenId &&item.Language == input.FromLanguage && item.TenantId == input.FromTenantId && item.IsDeleted == false);

            if (fromFileObjects.Count > 0)
            {
                var toFileObjects = _fileObjectRepository.GetAllList(
                        item => item.ContentId == input.ToContentId && item.Language == input.ToLanguage && item.TenantId == input.ToTenantId);

                foreach (var from in fromFileObjects)
                {
                    var isExist = false;
                    foreach (var to in toFileObjects)
                    {
                        if(from.Id == to.SourceID)
                        {
                            isExist = true;
                            _fileObjectDataStoreManage.UpdateFileObjectSync(to, from);
                            break;
                        }
                    }

                    if (!isExist)
                    {
                        _fileObjectDataStoreManage.CreateFileObjectSync(from, new DataProcessingStore
                        {
                            TargetLanguage = input.ToLanguage,
                            ToTenantId = input.ToTenantId,
                            AssociateId = input.ToContentId
                        });
                    }
                }
            }
            
        }
    }
}
